I've read in several places that the key difference is that this is lexically bound in arrow functions. That's all well and good, but I don't actually know what that means.
I know it means it's unique within the confines of the braces defining the function's body, but I couldn't actually tell you the output of the following code, because I have no idea what this is referring to, unless it's referring to the fat arrow function itself....which doesn't seem useful.
var testFunction = () => { console.log(this) };
testFunction();
Arrow functions capture the this value of the enclosing context
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
So, to directly answer your question, this inside your arrow function would have the same value as it did right before the arrow function was assigned.
In order to provide the big picture I'm going to explain both, dynamic and lexical binding.
this refers to the object the method is called on. This is a regularly to be read sentence on SO. But it is still only a phrase, pretty abstract. Is there a corresponding code pattern to this sentence?
Yes there is:
const o = {
m() { console.log(this) }
}
// the important patterns: applying methods
o.m(); // logs o
o["m"](); // logs o
m is a method because it relies on this. o.m() or o["m"]() means m is applied to o. These patterns are the Javascript translation to our famous phrase.
There is another important code pattern that you should pay attention to:
"use strict";
const o = {
m() { console.log(this) }
}
// m is passed to f as a callback
function f(m) { m() }
// another important pattern: passing methods
f(o.m); // logs undefined
f(o["m"]); // logs undefined
It is very similar to the previous pattern, only the parenthesis are missing. But the consequences are considerable: When you pass m to the function f, you pull outm of its object/context o. It is uprooted now and this refers to nothing (strict mode assumed).
Arrow functions don't have their own this/super/arguments binding. They inherit them from their parent lexical scope:
const toString = Object.prototype.toString;
const o = {
foo: () => console.log("window", toString.call(this)),
bar() {
const baz = () => console.log("o", toString.call(this));
baz();
}
}
o.foo() // logs window [object Window]
o.bar() // logs o [object Object]
Apart from the global scope (Window in browsers) only functions are able to form a scope in Javascript (and {} blocks in ES2015). When the o.foo arrow function is called there is no surrounding function from which baz could inherit its this. Consequently it captures the this binding of the global scope which is bound to the Window object.
When baz is invoked by o.bar, the arrow function is surrounded by o.bar (o.bar forms its parent lexical scope) and can inherit o.bar's this binding. o.bar was called on o and thus its this is bound to o.
Hope this code show could give you clearer idea. Basically, 'this' in arrow function is the current context version of 'this'. See the code:
// 'this' in normal function & arrow function
var this1 = {
number: 123,
logFunction: function () { console.log(this); },
logArrow: () => console.log(this)
};
this1.logFunction(); // Object { number: 123}
this1.logArrow(); // Window